package com.exin.openfeign;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

public class FeignReduceProxy implements InvocationHandler {


    /** The entity class. */
    protected Class<?> entityClass;


    protected DefaultFeignReduceBuilder builder;

    
    protected Class mapperInterface;
    protected Map<Method ,HandlerMethod> handlerMethodMap;

    /** 避免每次调用都反射创建 */
    private MethodHandles.Lookup lookup;
    
    ApplicationContext applicationContext;


    /**
     * @param builder
     * @param sqlManager
     * @param mapperInterface
     */
    public FeignReduceProxy(Class<?> mapperInterface , Map<Method ,HandlerMethod> handlerMethodMap  , ApplicationContext applicationContext) {
        super();
        this.mapperInterface(mapperInterface);
        this.mapperInterface = mapperInterface;
        this.handlerMethodMap = handlerMethodMap;
        this.applicationContext = applicationContext;
    }


    /**
     * Mapper interface.
     *
     * @param mapperInterface the dao2 interface
     * @return the dao2 proxy
     */
    public FeignReduceProxy mapperInterface(Class<?> mapperInterface) {
        this.onResolveEntityClassFromMapperInterface(mapperInterface);
        return this;
    }


    /**
     * Entity class.
     *
     * @param entityClass the entity class
     * @return the dao2 proxy
     */
    public FeignReduceProxy entityClass(Class<?> entityClass) {
        this.entityClass = entityClass;
        return this;
    }

    /**
     * 获取BaseMapper&lt;EntityClass&gt;接口的泛型实体参数类.
     *
     * @param mapperInterface the dao2 interface
     */
    protected void onResolveEntityClassFromMapperInterface(Class<?> mapperInterface) {
        if (mapperInterface.isInterface()) {
            Type[] faces = mapperInterface.getGenericInterfaces();
            if (faces.length > 0 && faces[0] instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) faces[0];
                if (pt.getActualTypeArguments().length > 0) {
                    this.entityClass = (Class<?>) pt.getActualTypeArguments()[0];

                }
            }
        } else {
            throw new IllegalArgumentException("mapperInterface is not interface.");
        }
    }


    /**
     * Invoke.
     *
     * @param proxy  the proxy
     * @param method the method
     * @param args   the args
     * @return the object
     * @throws Throwable the throwable 
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       
        String methodName = method.getName();
        if(methodName.equals("toString")){
        	return "Feign Mapper "+mapperInterface;
        }
        HandlerMethod handlerMethod = handlerMethodMap.get(method);
        Object target = applicationContext.getBean((String)handlerMethod.getBean());
        return handlerMethod.getMethod().invoke(target, args);
        
    }
    
    public String toString(){
    	return "Feign Self Proxy";
    }


}
